package com.jin.webvideo.base.linkedfile;

import com.jin.webvideo.base.linkedfile.io.SeekableDataInputStream;

import java.io.*;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;

public class LinkedFile implements Closeable, Serializable {

    public static final byte MAGIC = 0x11;
    @Serial
    private static final long serialVersionUID = -8883980327558757236L;

    private transient SeekableDataInputStream inputStream;
    // 文件版本
    private int version = 1;
    // 文件路径
    private URI path;
    // 文件描述
    private String description = "";
    // 最后修改时间
    private long lastModified;

    private boolean loaded = false;

    private List<LinkedItem> dirZone = new ArrayList<>(0);
    public LinkedFile() {

    }
    public LinkedFile(SeekableDataInputStream inputStream, URI path) throws IOException {
        this.path = path;
        this.inputStream = inputStream;
        this.inputStream.seek(0);
    }

    public int getVersion() {
        return version;
    }

    public void setVersion(int version) {
        this.version = version;
    }

    public URI getPath() {
        return path;
    }

    public void setPath(URI path) {
        this.path = path;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public String getDescription() {
        return description;
    }

    public void setLastModified(long lastModified) {
        this.lastModified = lastModified;
    }

    public long getLastModified() {
        return lastModified;
    }

    public void setDirZone(List<LinkedItem> dirZone) {
        this.dirZone = dirZone;
    }

    public List<LinkedItem> getDirZone() {
        return dirZone;
    }


    // 加载目录区数据
    public void loadDirZone() throws IOException {
        if (loaded) {
            return;
        }
        this.inputStream.seek(0);
        if (!LinkedFile.isVFile(this.inputStream.read())) {
            throw new UnsupportedEncodingException();
        }
        this.version = this.inputStream.readUnsignedShort();
        int count = this.inputStream.readUnsignedShort();

        this.lastModified = this.inputStream.readLong();
        this.description = this.inputStream.readUTFBlockByUnsignedShort();


        this.dirZone = new ArrayList<>(count);
        for (int i = 0; i < count; i++) {
            this.dirZone.add(new LinkedItem(this,
                    this.inputStream.readLong(),
                    this.inputStream.readUnsignedInt(),
                    this.inputStream.readLong(),
                    this.inputStream.readLong()));
        }
        loaded = true;
    }
    // 加载所有数据
    public void load() throws IOException {
        loadDirZone();
        for (LinkedItem item : this.dirZone) {
            item.load();
        }
    }

    public SeekableDataInputStream getInputStream() {
        return inputStream;
    }


    public long getLength() {
        if (dirZone.size() > 0) {
            LinkedItem item = dirZone.get(dirZone.size() - 1);
            return item.getStart() + item.getLength();
        }
        return 0;

    }

    @Override
    public String toString() {
        return "VFile{" +
                "file=" + inputStream +
                ", version=" + version +
                ", path=" + path +
                ", dirZone=" + dirZone +
                '}';
    }

    @Override
    public void close() throws IOException {
        inputStream.close();
    }

    public static boolean isVFile(int magic) {
        return magic == LinkedFile.MAGIC;
    }
}
